﻿// -----------------------------------------------------------------------
// <copyright file="TestBaseClass.cs">
// Copyright (c) 2012-2013 Andrey Veselov. All rights reserved.
// License:  Microsoft Public License (MS-PL)
// Contacts: http://andrey.moveax.com  andrey@moveax.com
// </copyright>
// -----------------------------------------------------------------------

namespace Moveax.DataAccess.Cqrs.Highway.EF.UnitTests
{
	using System.Collections.Generic;
	using System.Reflection;
	using Microsoft.VisualStudio.TestTools.UnitTesting;
	using Moveax.DataAccess.Cqrs;
	using Moveax.DataAccess.Cqrs.Highway.Bootstrappers.Autofac;
	using Moveax.DataAccess.Cqrs.Highway.EF;
	using Moveax.DataAccess.Cqrs.Highway.EF.UnitTests.DataAccess.Database;
	using Moveax.DataAccess.Cqrs.Highway.EF.UnitTests.DataAccess.Database.Dto;
	using Moveax.DataAccess.Cqrs.Highway.EF.UnitTests.Model.Commands.Links;
	using Moveax.DataAccess.Cqrs.Highway.EF.UnitTests.Model.Commands.Users;
	using Moveax.DataAccess.Cqrs.Highway.UnitTests.Model;
	using Moveax.DataAccess.Cqrs.Highway.UnitTests.Model.Queries;

	[TestClass]
	public class TestClassBase
	{
		protected readonly IUnitOfWorkFactory _unitOfWorkFactory;

		protected readonly User _sampleData = new User() {
			Name = "Andrey Veselov",
			Email = "andrey@moveax.com",
			IsDisabled = false,
			Links = new List<Link>() {
				new Link() { Title = "Project home page", Url = @"http://highway.codeplex.com/"},
				new Link() { Title = "Andrey on .NET blog", Url = @"http://andrey.moveax.com/" }
			}
		};

		public TestClassBase()
		{
			// Load queries and command handlers from test assemblies
			var currentAssembly = typeof(TestClassBase).Assembly;
			var modelsAssembly = Assembly.Load("Moveax.DataAccess.Cqrs.Highway.UnitTests.Model");
			var dalAssembly = Assembly.Load("Moveax.DataAccess.Cqrs.Highway.UnitTests.DataAccess");
			var builder = new CqrsDependencyResolverBuilder();

			builder.CollectQueryInterfaces(modelsAssembly);
			builder.CollectQueryInterfaces(currentAssembly);
			builder.CollectCommands(modelsAssembly);
			builder.CollectCommands(currentAssembly);

			builder.BindQueries(dalAssembly);
			builder.BindQueries(currentAssembly);
			builder.BindCommandHandlers(dalAssembly);
			builder.BindCommandHandlers(currentAssembly);

			this._unitOfWorkFactory = new EFUnitOfWorkFactory<TestDbContext>(builder.Build());
		}

		[TestInitialize]
		public void TestInitialize()
		{
			var userCommand = new CreateUserCommand(this._sampleData.Name, this._sampleData.Email, this._sampleData.IsDisabled, null);
			this._unitOfWorkFactory.ExecuteSingleCommand(userCommand);

			this._sampleData.Id = userCommand.Id;
			this._sampleData.Created = userCommand.Created;

			foreach (Link link in this._sampleData.Links) {
				var linkCommand = new CreateLinkCommand(userCommand.Id, link.Title, link.Url);
				this._unitOfWorkFactory.ExecuteSingleCommand(linkCommand);
				link.Id = linkCommand.Id;
				link.UserProfileId = userCommand.Id;
			}
		}

		[TestCleanup]
		public void TestCleanup()
		{
			using (var unitOfWork = this._unitOfWorkFactory.Create()) {
				var entities = unitOfWork.ResolveQuery<IGetAllQuery>().Execute<UserDto>();

				foreach (var entity in entities) {
					var command = new RemoveUserCommand(entity.Id);
					unitOfWork.ExecuteCommand(command);
				}

				unitOfWork.Commit();
			}
		}

		[AssemblyCleanup]
		public static void AssemblyCleanup()
		{
			// Remove database
			using (var context = new TestDbContext())
				context.Database.Delete();
		}

		protected void InsertObjectsIntoRepository(IUnitOfWork unitOfWork, int objectsCount)
		{
			for (var i = 1; i <= objectsCount; ++i) {
				var cmd = new CreateUserCommand(
					name: string.Format("UserName{0}", i),
					email: string.Format("userName{0}@site{0}.com", i),
					isDisabled: (i % 2) == 1,
					links: new[] { new Link() {
							Title = string.Format("Link{0}", i),
							Url = string.Format(@"http://site{0}.com", i)
						}});

				unitOfWork.ExecuteCommand(cmd);
			}
		}
	}
}